﻿using System;
using System.Linq.Expressions;
using DelegateExpressionizer;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace DelegateToExpression.Test
{
    [TestClass]
    public class UnitTest1
    {
        private static readonly Func<Expression, string> debugView = BuildDebugView();

        private static Func<Expression, string> BuildDebugView()
        {
            var parameter = Expression.Parameter(typeof(Expression), "e");
            return Expression.Lambda<Func<Expression, string>>(Expression.Property(parameter, "DebugView"), parameter).Compile();
        }

        protected static void Test(string expected, Delegate compiled)
        {
            var decompiled = compiled.ToExpression();
            Assert.AreEqual(expected.Trim(), debugView(decompiled));
        }

        protected static void Test(Expression expected, Delegate compiled)
        {
            var decompiled = compiled.ToExpression();

            Assert.AreEqual(expected.ToString(), decompiled.ToString());
            Assert.AreEqual(debugView(expected), debugView(decompiled));
        }

        [TestMethod]
        public void CanUseEmptyIf()
        {
            Action action = () =>
            {
                if (true)
                {
                    return;
                }

            };

            var expr = action.ToExpression();

            ParameterExpression var0 = Expression.Variable(typeof(bool), "var0");
            var expectedE =
                Expression.Lambda<Action>(
                    Expression.Block(new[] { var0 }, new Expression[]
                    {
                        Expression.IfThen(Expression.Constant(true), Expression.Default(typeof(void)))
                    }
                ));
            Test(expectedE, action);
        }

        [TestMethod]
        public void CanUseIfWithDifferentBranchesAssignAndVoid()
        {
            bool c = false;
            Action action = () =>
            {
                if (c)
                {
                    var d = c;
                }

            };

            var expr = action.ToExpression();

            const string expected = @".Lambda #Lambda1<System.Action`1[DelegateToExpression.Test.UnitTest1+<>c__DisplayClass4]>(DelegateToExpression.Test.UnitTest1+<>c__DisplayClass4 $this)
{
    .Block(
        System.Boolean $var0,
        System.Boolean $var1) {
        $var1 = $this.c == False;
        .If ($var1 != False) {
            .Default(System.Void)
        } .Else {
            $var0 = $this.c
        }
    }
}";
            Test(expected, action);
        }
    }
}
